#include using namespace std; const int nax = 1e6 + 5; vector> w[nax]; vector path; bool vis[nax]; int cycle[nax], cycle_len[nax]; #define ver first #define cost second pair par[nax][20]; int h_unit[nax], h_true[nax]; void start_dfs(int a) { assert(!vis[a]); vis[a] = true; path.push_back(a); for(pair edge : w[a]) { int b = edge.ver; if(b == par[a][0].ver) continue; if(vis[b]) { if(cycle[a] == a && cycle[b] == a) continue; for(int i = (int) path.size() - 1; path[i] != b; --i) { int x = path[i]; assert(!cycle[x]); cycle[x] = b; cycle_len[b] += par[x][0].cost; } cycle_len[b] += edge.cost; cycle[b] = b; } else { h_unit[b] = h_unit[a] + 1; par[b][0] = {a, edge.cost}; for(int i = 1; i < 20; ++i) { int tmp = par[b][i-1].ver; par[b][i] = {par[tmp][i-1].ver, par[b][i-1].cost + par[tmp][i-1].cost}; } start_dfs(b); } } path.pop_back(); } int h_fake(int a) { return par[a][19].cost; } void dfs_true_len(int a) { vis[a] = true; int boss = cycle[a]; if(a == boss) h_true[a] = h_true[par[a][0].ver] + par[a][0].cost; else { int tmp = h_fake(a) - h_fake(boss); h_true[a] = h_true[boss] + min(tmp, cycle_len[boss] - tmp); } for(pair edge : w[a]) { int b = edge.ver; if(!vis[b]) dfs_true_len(b); } } int distSameCycle(int a, int b) { assert(cycle[a] > 0 && cycle[a] == cycle[b]); int d = abs(h_fake(a) - h_fake(b)); return min(d, cycle_len[cycle[a]] - d); } int lca(int a, int b) { if(h_unit[a] < h_unit[b]) swap(a, b); assert(h_unit[a] >= h_unit[b]); for(int i = 19; i >= 0; --i) if(h_unit[a] - (1 << i) >= h_unit[b]) a = par[a][i].ver; assert(h_unit[a] == h_unit[b]); for(int i = 19; i >= 0; --i) if(par[a][i].ver != par[b][i].ver) { a = par[a][i].ver; b = par[b][i].ver; } if(a != b) { a = par[a][0].ver; b = par[b][0].ver; } assert(a == b && a != 0); return a; } // finds the distance between ancestor and descendant int distUpDown(int a, int b) { if(h_unit[a] < h_unit[b]) swap(a, b); int memo_a = a; for(int i = 19; i >= 0; --i) { int maybe = par[a][i].ver; if(maybe == 0) continue; if(h_unit[maybe] >= h_unit[b] && cycle[maybe] != cycle[b]) a = maybe; } if(cycle[a] != cycle[b]) a = par[a][0].ver; assert(cycle[a] == cycle[b]); return distSameCycle(a, b) + h_true[memo_a] - h_true[a]; } int query(int a, int b) { int c = lca(a, b); return distUpDown(a, c) + distUpDown(b, c); } void add_edge(int a, int b, int c) { w[a].push_back({b,c}); w[b].push_back({a,c}); } bool range(int a, int b, int c) { return a <= b && b <= c; } int main() { int n, m; scanf("%d%d", &n, &m); assert(range(2,n,100*1000)); assert(range(1,m,200*1000)); set> edges; while(m--) { int a, b, c; scanf("%d%d%d", &a, &b, &c); assert(1 <= min(a,b) && max(a,b) <= n); assert(range(1,c,10*1000)); assert(a != b); if(a > b) swap(a, b); assert(!edges.count({a,b})); edges.insert({a,b}); add_edge(a, b, c); } ++n; int root = n; add_edge(1, root, 42); start_dfs(root); for(int i = 1; i <= n; ++i) { assert(vis[i]); if(cycle[i] == 0) cycle[i] = i; } for(int i = 0; i <= n + 1; ++i) vis[i] = false; dfs_true_len(root); int q; scanf("%d", &q); assert(range(1,q,100*1000)); while(q--) { int a, b; scanf("%d%d", &a, &b); printf("%d\n", query(a, b)); } }